// #[macro_use]
// extern crate lazy_static;
extern crate regex;

// use std::{fs,mem};
// use std::io::{BufReader, Read};
use std::env;

mod common;
mod accelary;
mod oper;
mod xlsx;
const  MODE_EXTRACT:i32 = 0;
const MODE_REPLACE:i32 = 2;
const  MODE_DEL:i32 = 1;
const MODE_GREEP:i32 = 3;
const MODE_GREEP_BY:i32 =4;

fn help(){
    println!("{}",r#"

lines [options]   file/-
    # when last is "-" will recv from stdin
    # when last is a file name will handle this file

-l[loc] location 
    exm:fr:end   /    fr:end,start_column:end:column 
-T  [false] true to use thread to handle
-e[-extract]  extract mode
    example:  extract \w+
-s[-split] split mode
    example:  split 
-r[-replace]  replace to example  -r "\W" as ","
-v[-del]  del mode
-grepby

## Document

example  $0  split r#\\W  col 2: row :1000    #  取前一千个每行用 正则 \W 分割， 取第二列之后

    "#)
}

#[warn(deprecated)]
fn main() {
    // let mut fname :String = String::new();
    let mut oper  :Vec<String> = vec![];
    let mut tag ="";
    let mut thread_tag = 0;
    // let mut buffer  = String::new();
    let fname = env::args().last().unwrap();
    let mut thread_num = 1;
    let mut found = false;
    let mut loc = common::Loc::new();
    for arg in env::args(){
        match Some(arg.as_str()) {
            Some("-h") => {
                help();
                return;
            }
            Some("-l") => {
                tag = "loc"
            }
            Some("-loc") => {
                tag = "loc"
            }
            Some("-T") => {
                thread_tag = 1;
                tag = "thread"
            }
            Some("-r") => {
                loc.set_mode( MODE_REPLACE);
                tag = "replace"
            }
            Some("-replace") => {
                loc.set_mode( MODE_REPLACE);
                tag = "replace"
            }
            Some("-e") => {

                loc.set_mode( MODE_EXTRACT);
                tag = "oper"
            },
            Some("-extract") => {
                loc.set_mode(MODE_EXTRACT);
                tag = "oper"
            },
            Some("-s") => {
                tag = "split";
            },
            Some("-split") => {
                tag = "split";
            }
            Some("-v") => {
                loc.set_mode( MODE_DEL);
                tag = "oper"
            }
            Some("-del") => {
                loc.set_mode( MODE_DEL);
                tag = "oper"
            }
            Some("-grep") => {
                loc.set_mode( MODE_GREEP);
                tag = "grep"
            }
            Some("-grepby") => {
                loc.set_mode( MODE_GREEP_BY);
                loc.point_to_loc = 1;
                tag = "grepby";
                loc.other_loc = Some(Box::new(common::Loc::new()))
            }
            Some("-row") => {
                tag = "row"
            }
            Some("-col") => {
                tag ="col"
            }
            _ => {
                if tag == "oper"{
                    if arg != fname{
                        oper.push(arg.to_string());
                    
                    }
               }else if tag == "thread"{
                    thread_num = arg.parse::<i32>().unwrap();
                } else if tag =="grep"{
                    loc.re_string = arg.trim().to_owned();
                    tag = ""
                }else if tag =="grepby"{
                    loc.re_string = arg.trim().to_owned();
                    tag = ""
                } else if tag == "loc"{
                    loc.set_loc(arg.trim());
                    tag = ""
                }else if tag == "row"{
                    loc.set_rows(arg.trim());
                    tag = ""
                }else if tag == "col"{
                    loc.set_columns(arg.trim());
                    tag = ""
                }else if tag == "split"{
                    loc.set_split_by(&arg);
                    tag =""
                } else if tag == "replace" {
                    if !found && arg != "as" {
                        oper.push(arg.to_string());
                    }else if !found && arg == "as" {
                        found = true
                    }else{
                        if arg != " "{
                            loc.replace_to = arg.to_string().trim().to_owned();
                        }else{
                            loc.replace_to = arg.to_string().to_owned();
                        }
                        tag = ""
                    }
                }
            }
        }
    }
    
    
    // let args =  &env::args().collect::<Vec<String>>();
    println!("fname: {} oper : {:?}",fname,loc.grep_by_vec.len());
    let oper_str = oper.join(" ");
    if loc.re_string == ""{
        loc.re_string = oper_str;
    }
    if loc.point_to_loc > 0{
        (&mut loc).collect_grep_by();
    }
    if fname.as_str() == "-"{
        if thread_tag > 0{
            accelary::handle_each_line_async(oper::oper_line_function, loc);
        }else{
            common::handle_each_line(oper::oper_line_function, loc);
        }
        
    }else{
        if thread_tag > 0{
            accelary::handle_each_line_file_async(fname.as_ref(),oper::oper_line_function, loc,thread_num).expect("handle error !");
        }else{
            if fname.ends_with(".xlsx"){
                match xlsx::handle_lines(fname.as_ref(), "", xlsx::oper, loc){
                    Err(e) => {
                        println!("[Err] {}", e);
                    },
                    Ok(_) =>{}
                
                }
            }else{
                
                match common::handle_each_line_file(fname.as_ref(), oper::oper_line_function,loc){
                    Err(e) => {
                        println!("[Err] {}", e);
                    },
                    Ok(_) =>{}
                }
            }
        }
        
        // println!("buf : {}",buffer)
    }
    
}
